<template>
  <div>
    <h2>msg: {{ msg }}</h2>
    <h2>length: {{ length }}</h2>
    <h2>length: {{ length }}</h2>
    <button @click="update">更新</button>
  </div>
</template>

<script>
export default {
  name: 'ReactiveTest',
  data () {
    return {
      msg: 'atguigu'
    }
  },

  computed: { // computedWatcher
    length () {
      debugger
      console.log('computed length')
      return this.msg.length
    }
  },

  watch: {
    msg: {
      handler () {
        debugger;
        console.log('watch msg change', this.length)
      },
      immediate: true
    }
  },

  methods: {
    update () {
      this.msg = 'atguigu22'
    }
  }
}

/* 
computedWatcher
	计算属性Watcher, 每个计算属性都创建一个
	包含一个计算属性函数的自定义的回调, 用于计算产生属性值
	初始化computed时创建
	lazy属性为true, dirty属性初始为true
	初始化阶段
		当读取计算属性时, 由于dirty是true, 执行计算属性回调得到属性值显示, 同时保存到value属性上, 并将dirty置为false
		如果再次读取, 由于dirty是false, 直接返回value属性值  ==> 使用缓存
	更新阶段
		当依赖的data属性发生改变时, 只是将dirty变true
		当读取计算属性值, 与上面一样的逻辑

userWatcher
	用户/监视Watcher, 每个watch和每次$watch调用都创建一个
	包含一个监视自定义的回调
	初始化watch时创建
	user属性为true
	监视回调默认初始时不调用, 只有immediate配置为true时, 才会调用
	如果deep配置为true, 它会对监视的属性对象中所有层次的属性都进行setter监视

renderWatcher
	渲染Watcher, 每个组件创建一个
	包含一个渲染组件的内置回调  updateComponent => patch(render())
	挂载/mount时创建
	lazy和user属性都为false


在初始化data时, 会创建Observer对象, 通过defineReactive()利用defineProperty给data中所有层次属性添加getter和setter
同时为每个属性都创建对应的dep对象, 用于收集依赖和派发更新
收集依赖
	将watcher添加到dep的subs数组中
	在getter中收集依赖 (初始化阶段)
		userWatcher: 在初始创建userWatcher中收集到dep中, 最早
		renderWatcher: 在初始创建renderWatcher中, 执行render中将当前watcher收集到dep中
		computedWatcher: 在读取计算属性(render或watch回调中), 调用计算属性回调, 将当前watcher收集到dep中
派发更新
	调用dep的subs数组中所有watcher去更新
	在setter中派发更新(更新阶段): 当更新了一个data数据, 就会调用setter
		computedWatcher: 只是将dirty变为true 注意: 现在不执行回调, 在执行userWatcher或renderWatcher的回调时才会执行
		userWatcher和renderWatcher: 将watcher添加到内部一个queue队列中, 准备异步执行
*/
</script>
